package com.jiaming.employee.common.utils;

import com.jiaming.employee.common.exception.InvalidTokenException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

@Slf4j
public class JwtUtil {
    /**
     * token 过期时间，基于token内容过期时间超出300秒，即超出5分钟
     * 例如：token 中 jwtinfo 5分钟后过期，那么该 token 过期时间是 5+5，即10分钟后
     */
    private static final long EXPIRE_TIME = 300L;
    /**
     * token 加密私钥，不能泄露
     */
    private static final String SCERET_KEY = "cd38f925c72643e4a1c9138cb9c85dc1";

    // 使用默认的私钥和过期时间创建 token
    public static String createSign(JwtInfo jwtInfo) {
        return createSign(jwtInfo, SCERET_KEY, EXPIRE_TIME);
    }

    // 解析 token 字符串，获取 token 中的信息
    public static JwtInfo getSecretInfo(String token) {
        return getSecretInfo(token, SCERET_KEY);
    }

    // 使用自定义的私钥创建 token
    public static String createSign(JwtInfo jwtInfo, String secretKey) {
        return createSign(jwtInfo, secretKey, EXPIRE_TIME);
    }

    // 判断 token 中的内容是否过期
    public static boolean isExpired(Date expiredDate) {
        // 假如 token 中的内容还有5分钟就要失效，那么就认为已失效，需要生成新的token
        // 因为 token 在5分钟后失效期前，客户端与后台进行了交互，那么就会生成新的token，保证客户端的连续访问有效性
        return System.currentTimeMillis() > expiredDate.getTime() + 300000;
    }

    /**
     * 创建签名token
     * @param jwtInfo 账户信息，必须包含账户ID、名称和密码
     * @param expireTime token jwtinfo 过期时间，单位秒
     * @return
     */
    public static String createSign(JwtInfo jwtInfo, String secretKey, long expireTime) {
        // token过期日期
        Date date = new Date(jwtInfo.getExpiredDate().getTime() + expireTime * 1000);
        Claims claims = Jwts.claims();
        claims.put("accountId", jwtInfo.getId());
        claims.put("loginName", jwtInfo.getLoginName());
        return Jwts.builder()
                .setClaims(claims) // 设置token中携带的加密信息
                .setExpiration(date) // 设置token的过期时间
                .signWith(SignatureAlgorithm.HS512, secretKey) // 加密签名
                .compact();
    }

    /**
     * 获取加密信息
     * @param token
     * @param secretKey
     * @return
     */
    public static JwtInfo getSecretInfo(String token, String secretKey) {
        try {
            Claims body = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
            JwtInfo jwtInfo = new JwtInfo();
            jwtInfo.setId(body.get("accountId", Integer.class));
            jwtInfo.setLoginName(body.get("loginName", String.class));
            jwtInfo.setExpiredDate(body.getExpiration());
            return jwtInfo;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            throw new InvalidTokenException();
        }
    }

    // 示例
    public static void main(String[] args) {
//        // 创建 token 中需要携带的非敏感信息
//        JwtInfo jwtInfo = new JwtInfo();
//        jwtInfo.setId(1);
//        jwtInfo.setLoginName("admin");
//        jwtInfo.setExpiredDate(DateUtil.offsetDay(new Date(), 3));
//        System.out.println(jwtInfo);
//
//        // 生成 token 字符串
//        String token = JwtUtil.createSign(jwtInfo);
//        System.out.println(token);
//
//        // 解密 token 字符串，返回 token 中携带的信息
//        JwtInfo secretInfo = getSecretInfo(token);
//        System.out.println(secretInfo);
//        // 判断 token 内容 是否过期
//        System.out.println(isExpired(secretInfo.getExpiredDate()));

        String token2 = "eyJhbGciOiJIUzUxMiJ9.eyJhY2NvdW50SWQiOjEsImxvZ2luTmFtZSI6ImFkbWluIiwiZXhwIjoxNjE3MjQ0NTQ2fQ.1WahGJsI8r27BKf0nskFGo8Yws-a-H9eM8YIX-5Z7GnI3LG5lx846jMKwFjXUVZjwZ01O0TI3j2mXsDqPGWDeA";
        getSecretInfo(token2);
    }
}
